/***************************************************************
 * Name:      DFRawParserMain.cpp
 * Purpose:   Code for Application Frame
 * Author:    Timothy Sassone (timothy.s.dev@gmail.com)
 * Created:   2010-03-09
 * Copyright: Timothy Sassone (timothy-s-dev.50webs.com)
 * License:
 **************************************************************/

#include "wx_pch.h"
#include "DFRawParserMain.h"
#include <wx/msgdlg.h>

//(*InternalHeaders(DFRawParserFrame)
#include <wx/intl.h>
#include <wx/string.h>
//*)

#include <boost/xpressive/xpressive.hpp>
#include "c_tag.h"
#include "TextInputDialog.h"
#include "DoubleTextInputDialog.h"
#include "misc_functions.h"
#include "xmlParser.h"

const float _VERSION = 1.10;

/***REGEX EXPRESSIONS***/
using namespace boost::xpressive;
mark_tag FT_Contents(1);
sregex Reg_FindTags = "[" >> (FT_Contents = +(+_w|_s|_d|':'|'_')) >> "]";

//helper functions
enum wxbuildinfoformat {
    short_f, long_f };

wxString wxbuildinfo(wxbuildinfoformat format)
{
    wxString wxbuild(wxVERSION_STRING);

    if (format == long_f )
    {
#if defined(__WXMSW__)
        wxbuild << _T("-Windows");
#elif defined(__UNIX__)
        wxbuild << _T("-Linux");
#endif

#if wxUSE_UNICODE
        wxbuild << _T("-Unicode build");
#else
        wxbuild << _T("-ANSI build");
#endif // wxUSE_UNICODE
    }

    return wxbuild;
}

vector<c_tag> tag_list;

//(*IdInit(DFRawParserFrame)
const long DFRawParserFrame::ID_LABEL_HELLO = wxNewId();
const long DFRawParserFrame::ID_LISTBOX_TAGS = wxNewId();
const long DFRawParserFrame::ID_TEXTCTRL_TAG = wxNewId();
const long DFRawParserFrame::ID_BUTTON_TAG = wxNewId();
const long DFRawParserFrame::ID_BUTTON_DELTAG = wxNewId();
const long DFRawParserFrame::ID_PANEL3 = wxNewId();
const long DFRawParserFrame::ID_STATICLINE1 = wxNewId();
const long DFRawParserFrame::ID_STATICTEXT_ARGUMENTS = wxNewId();
const long DFRawParserFrame::ID_LISTBOX_ARGUMENTS = wxNewId();
const long DFRawParserFrame::ID_TEXTCTRL_ARGUMENT = wxNewId();
const long DFRawParserFrame::ID_BUTTON_ARGUMENT = wxNewId();
const long DFRawParserFrame::ID_BUTTON_DELARG = wxNewId();
const long DFRawParserFrame::ID_PANEL2 = wxNewId();
const long DFRawParserFrame::ID_STATICTEXT_CHILDREN = wxNewId();
const long DFRawParserFrame::ID_LISTBOX_CHILDREN = wxNewId();
const long DFRawParserFrame::ID_TEXTCTRL_CHILD = wxNewId();
const long DFRawParserFrame::ID_BUTTON_CHILD = wxNewId();
const long DFRawParserFrame::ID_BUTTON_COPYALL = wxNewId();
const long DFRawParserFrame::ID_BUTTON_DELCHILD = wxNewId();
const long DFRawParserFrame::ID_PANEL1 = wxNewId();
const long DFRawParserFrame::ID_STATICLINE3 = wxNewId();
const long DFRawParserFrame::ID_BUTTON_PARSETOXML = wxNewId();
const long DFRawParserFrame::ID_BUTTON_PARSETORAW = wxNewId();
const long DFRawParserFrame::ID_GAUGE_PARSE = wxNewId();
const long DFRawParserFrame::ID_CHECKBOX_XMLNAMES = wxNewId();
const long DFRawParserFrame::ID_CHECKBOX_RAWNAMES = wxNewId();
const long DFRawParserFrame::ID_PANEL4 = wxNewId();
const long DFRawParserFrame::idMenuNew = wxNewId();
const long DFRawParserFrame::idMenuSave = wxNewId();
const long DFRawParserFrame::idMenuLoad = wxNewId();
const long DFRawParserFrame::idMenuQuit = wxNewId();
const long DFRawParserFrame::idMenuHelp = wxNewId();
const long DFRawParserFrame::idMenuAbout = wxNewId();
const long DFRawParserFrame::ID_STATUSBAR1 = wxNewId();
//*)

BEGIN_EVENT_TABLE(DFRawParserFrame,wxFrame)
    //(*EventTable(DFRawParserFrame)
    //*)
END_EVENT_TABLE()

DFRawParserFrame::DFRawParserFrame(wxWindow* parent,wxWindowID id)
{
    //(*Initialize(DFRawParserFrame)
    wxBoxSizer* BoxSizer4;
    wxBoxSizer* BoxSizer6;
    wxFlexGridSizer* FlexGridSizer4;
    wxBoxSizer* BoxSizer5;
    wxMenuItem* MenuItem2;
    wxMenuItem* MenuItem_Load;
    wxFlexGridSizer* FlexGridSizer3;
    wxFlexGridSizer* FlexGridSizer5;
    wxFlexGridSizer* FlexGridSizer2;
    wxBoxSizer* BoxSizer2;
    wxMenu* Menu1;
    wxMenuItem* MenuItem_Quit;
    wxBoxSizer* BoxSizer1;
    wxFlexGridSizer* FlexGridSizer6;
    wxFlexGridSizer* FlexGridSizer1;
    wxBoxSizer* BoxSizer3;
    wxMenu* Menu2;
    wxMenuBar* MenuBar;

    Create(parent, wxID_ANY, _("DF Raw Parser"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("wxID_ANY"));
    FlexGridSizer1 = new wxFlexGridSizer(0, 1, 0, 0);
    Panel3 = new wxPanel(this, ID_PANEL3, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER, _T("ID_PANEL3"));
    FlexGridSizer5 = new wxFlexGridSizer(0, 1, 0, 0);
    label_tags = new wxStaticText(Panel3, ID_LABEL_HELLO, _("Tags"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_LABEL_HELLO"));
    FlexGridSizer5->Add(label_tags, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    ListBox_Tags = new wxListBox(Panel3, ID_LISTBOX_TAGS, wxDefaultPosition, wxSize(427,128), 0, 0, wxLB_SINGLE|wxLB_NEEDED_SB, wxDefaultValidator, _T("ID_LISTBOX_TAGS"));
    FlexGridSizer5->Add(ListBox_Tags, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    BoxSizer1 = new wxBoxSizer(wxHORIZONTAL);
    TextCtrl_Tag = new wxTextCtrl(Panel3, ID_TEXTCTRL_TAG, _("New Tag"), wxDefaultPosition, wxSize(188,21), 0, wxDefaultValidator, _T("ID_TEXTCTRL_TAG"));
    BoxSizer1->Add(TextCtrl_Tag, 2, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    Button_Tag = new wxButton(Panel3, ID_BUTTON_TAG, _("Add Tag"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON_TAG"));
    BoxSizer1->Add(Button_Tag, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    FlexGridSizer5->Add(BoxSizer1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    Button_DelTag = new wxButton(Panel3, ID_BUTTON_DELTAG, _("Delete Tag"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON_DELTAG"));
    FlexGridSizer5->Add(Button_DelTag, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    Panel3->SetSizer(FlexGridSizer5);
    FlexGridSizer5->Fit(Panel3);
    FlexGridSizer5->SetSizeHints(Panel3);
    FlexGridSizer1->Add(Panel3, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    StaticLine1 = new wxStaticLine(this, ID_STATICLINE1, wxDefaultPosition, wxSize(10,-1), wxLI_HORIZONTAL, _T("ID_STATICLINE1"));
    FlexGridSizer1->Add(StaticLine1, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    FlexGridSizer4 = new wxFlexGridSizer(0, 3, 0, 0);
    Panel2 = new wxPanel(this, ID_PANEL2, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER, _T("ID_PANEL2"));
    FlexGridSizer2 = new wxFlexGridSizer(0, 1, 0, 0);
    StaticText_Arguments = new wxStaticText(Panel2, ID_STATICTEXT_ARGUMENTS, _("Arguments"), wxDefaultPosition, wxSize(53,14), 0, _T("ID_STATICTEXT_ARGUMENTS"));
    FlexGridSizer2->Add(StaticText_Arguments, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    ListBox_Arguments = new wxListBox(Panel2, ID_LISTBOX_ARGUMENTS, wxDefaultPosition, wxSize(244,63), 0, 0, 0, wxDefaultValidator, _T("ID_LISTBOX_ARGUMENTS"));
    FlexGridSizer2->Add(ListBox_Arguments, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    BoxSizer2 = new wxBoxSizer(wxHORIZONTAL);
    TextCtrl_Argument = new wxTextCtrl(Panel2, ID_TEXTCTRL_ARGUMENT, _("New Argument"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL_ARGUMENT"));
    BoxSizer2->Add(TextCtrl_Argument, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    Button_Argument = new wxButton(Panel2, ID_BUTTON_ARGUMENT, _("Add Argument"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON_ARGUMENT"));
    BoxSizer2->Add(Button_Argument, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    FlexGridSizer2->Add(BoxSizer2, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    Button_DelArg = new wxButton(Panel2, ID_BUTTON_DELARG, _("Delete Argument"), wxDefaultPosition, wxSize(100,21), 0, wxDefaultValidator, _T("ID_BUTTON_DELARG"));
    FlexGridSizer2->Add(Button_DelArg, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    Panel2->SetSizer(FlexGridSizer2);
    FlexGridSizer2->Fit(Panel2);
    FlexGridSizer2->SetSizeHints(Panel2);
    FlexGridSizer4->Add(Panel2, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    FlexGridSizer4->Add(43,20,1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    Panel1 = new wxPanel(this, ID_PANEL1, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER, _T("ID_PANEL1"));
    FlexGridSizer3 = new wxFlexGridSizer(0, 1, 0, 0);
    StaticText_Children = new wxStaticText(Panel1, ID_STATICTEXT_CHILDREN, _("Children"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT_CHILDREN"));
    FlexGridSizer3->Add(StaticText_Children, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    ListBox_Children = new wxListBox(Panel1, ID_LISTBOX_CHILDREN, wxDefaultPosition, wxSize(239,63), 0, 0, 0, wxDefaultValidator, _T("ID_LISTBOX_CHILDREN"));
    FlexGridSizer3->Add(ListBox_Children, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    BoxSizer3 = new wxBoxSizer(wxHORIZONTAL);
    TextCtrl_Child = new wxTextCtrl(Panel1, ID_TEXTCTRL_CHILD, _("New Child"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL_CHILD"));
    BoxSizer3->Add(TextCtrl_Child, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    Button_Child = new wxButton(Panel1, ID_BUTTON_CHILD, _("Add Child"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON_CHILD"));
    BoxSizer3->Add(Button_Child, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    FlexGridSizer3->Add(BoxSizer3, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    BoxSizer4 = new wxBoxSizer(wxHORIZONTAL);
    ButtonCopyAll = new wxButton(Panel1, ID_BUTTON_COPYALL, _("Copy All"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON_COPYALL"));
    BoxSizer4->Add(ButtonCopyAll, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    Button_DelChild = new wxButton(Panel1, ID_BUTTON_DELCHILD, _("Delete Child"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON_DELCHILD"));
    BoxSizer4->Add(Button_DelChild, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    FlexGridSizer3->Add(BoxSizer4, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    Panel1->SetSizer(FlexGridSizer3);
    FlexGridSizer3->Fit(Panel1);
    FlexGridSizer3->SetSizeHints(Panel1);
    FlexGridSizer4->Add(Panel1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    FlexGridSizer1->Add(FlexGridSizer4, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    StaticLine3 = new wxStaticLine(this, ID_STATICLINE3, wxDefaultPosition, wxSize(10,-1), wxLI_HORIZONTAL, _T("ID_STATICLINE3"));
    FlexGridSizer1->Add(StaticLine3, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    Panel4 = new wxPanel(this, ID_PANEL4, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER, _T("ID_PANEL4"));
    FlexGridSizer6 = new wxFlexGridSizer(0, 1, 0, 0);
    BoxSizer5 = new wxBoxSizer(wxHORIZONTAL);
    Button_ParseToXML = new wxButton(Panel4, ID_BUTTON_PARSETOXML, _("To XML"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON_PARSETOXML"));
    BoxSizer5->Add(Button_ParseToXML, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    Button_ParseToRAW = new wxButton(Panel4, ID_BUTTON_PARSETORAW, _("To RAW"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON_PARSETORAW"));
    BoxSizer5->Add(Button_ParseToRAW, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    FlexGridSizer6->Add(BoxSizer5, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    Gauge_Parse = new wxGauge(Panel4, ID_GAUGE_PARSE, 100, wxDefaultPosition, wxSize(377,19), wxGA_HORIZONTAL, wxDefaultValidator, _T("ID_GAUGE_PARSE"));
    Gauge_Parse->SetShadowWidth(2);
    Gauge_Parse->SetBezelFace(2);
    FlexGridSizer6->Add(Gauge_Parse, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    BoxSizer6 = new wxBoxSizer(wxHORIZONTAL);
    CheckBox_XMLNames = new wxCheckBox(Panel4, ID_CHECKBOX_XMLNAMES, _("Auto-lowercase XML Names"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHECKBOX_XMLNAMES"));
    CheckBox_XMLNames->SetValue(false);
    BoxSizer6->Add(CheckBox_XMLNames, 2, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    BoxSizer6->Add(-1,-1,1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    CheckBox_RAWNames = new wxCheckBox(Panel4, ID_CHECKBOX_RAWNAMES, _("Auto-capitalize RAW Names"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHECKBOX_RAWNAMES"));
    CheckBox_RAWNames->SetValue(false);
    BoxSizer6->Add(CheckBox_RAWNames, 2, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    FlexGridSizer6->Add(BoxSizer6, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    Panel4->SetSizer(FlexGridSizer6);
    FlexGridSizer6->Fit(Panel4);
    FlexGridSizer6->SetSizeHints(Panel4);
    FlexGridSizer1->Add(Panel4, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    SetSizer(FlexGridSizer1);
    MenuBar = new wxMenuBar();
    Menu1 = new wxMenu();
    MenuItem_New = new wxMenuItem(Menu1, idMenuNew, _("New Tag List"), _("Close the current tag list and open a new one."), wxITEM_NORMAL);
    Menu1->Append(MenuItem_New);
    MenuItem_Save = new wxMenuItem(Menu1, idMenuSave, _("Save Tag List"), _("Save the current tag list to a file."), wxITEM_NORMAL);
    Menu1->Append(MenuItem_Save);
    MenuItem_Load = new wxMenuItem(Menu1, idMenuLoad, _("Load Tag List"), _("Load a tag list."), wxITEM_NORMAL);
    Menu1->Append(MenuItem_Load);
    MenuItem_Quit = new wxMenuItem(Menu1, idMenuQuit, _("Quit\tAlt-F4"), _("Quit the application"), wxITEM_NORMAL);
    Menu1->Append(MenuItem_Quit);
    MenuBar->Append(Menu1, _("&File"));
    Menu2 = new wxMenu();
    MenuItem1 = new wxMenuItem(Menu2, idMenuHelp, _("Help\tF1"), _("Open the help-file."), wxITEM_NORMAL);
    Menu2->Append(MenuItem1);
    MenuItem2 = new wxMenuItem(Menu2, idMenuAbout, _("About\tF12"), _("Show info about DF Raw Parser"), wxITEM_NORMAL);
    Menu2->Append(MenuItem2);
    MenuBar->Append(Menu2, _("Help"));
    SetMenuBar(MenuBar);
    StatusBar = new wxStatusBar(this, ID_STATUSBAR1, 0, _T("ID_STATUSBAR1"));
    int __wxStatusBarWidths_1[1] = { -1 };
    int __wxStatusBarStyles_1[1] = { wxSB_NORMAL };
    StatusBar->SetFieldsCount(1,__wxStatusBarWidths_1);
    StatusBar->SetStatusStyles(1,__wxStatusBarStyles_1);
    SetStatusBar(StatusBar);
    FileDialog_OpenTagList = new wxFileDialog(this, _("Open Tag-List"), wxEmptyString, wxEmptyString, _("Tag List File (*.tl)|*.tl|All Files|*.*"), wxFD_DEFAULT_STYLE|wxFD_OPEN|wxFD_FILE_MUST_EXIST, wxDefaultPosition, wxDefaultSize, _T("wxFileDialog"));
    FileDialog_SaveTagList = new wxFileDialog(this, _("Save Tag-List"), wxEmptyString, wxEmptyString, _("Tag List File (*.tl)|*.tl|All Files|*.*"), wxFD_DEFAULT_STYLE|wxFD_SAVE, wxDefaultPosition, wxDefaultSize, _T("wxFileDialog"));
    FileDialog_Parse = new wxFileDialog(this, _("Parse RAW File"), wxEmptyString, wxEmptyString, _("DF Raw File (*.txt)|*.txt|All Files|*.*"), wxFD_DEFAULT_STYLE|wxFD_OPEN|wxFD_FILE_MUST_EXIST, wxDefaultPosition, wxDefaultSize, _T("wxFileDialog"));
    FileDialog_ParseToRaw = new wxFileDialog(this, _("Select an XML file to convert to .RAW"), wxEmptyString, wxEmptyString, _("XML File (*.xml)|*xml|All Files|*.*"), wxFD_DEFAULT_STYLE, wxDefaultPosition, wxDefaultSize, _T("wxFileDialog"));
    FlexGridSizer1->Fit(this);
    FlexGridSizer1->SetSizeHints(this);

    Connect(ID_LISTBOX_TAGS,wxEVT_COMMAND_LISTBOX_SELECTED,(wxObjectEventFunction)&DFRawParserFrame::SelectTag);
    Connect(ID_LISTBOX_TAGS,wxEVT_COMMAND_LISTBOX_DOUBLECLICKED,(wxObjectEventFunction)&DFRawParserFrame::RenameTag);
    Connect(ID_BUTTON_TAG,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&DFRawParserFrame::AddTag);
    Connect(ID_BUTTON_DELTAG,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&DFRawParserFrame::DeleteTag);
    Connect(ID_LISTBOX_ARGUMENTS,wxEVT_COMMAND_LISTBOX_DOUBLECLICKED,(wxObjectEventFunction)&DFRawParserFrame::RenameArgument);
    Connect(ID_BUTTON_ARGUMENT,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&DFRawParserFrame::AddArgument);
    Connect(ID_BUTTON_DELARG,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&DFRawParserFrame::DeleteArgument);
    Connect(ID_LISTBOX_CHILDREN,wxEVT_COMMAND_LISTBOX_DOUBLECLICKED,(wxObjectEventFunction)&DFRawParserFrame::RenaneChild);
    Connect(ID_BUTTON_CHILD,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&DFRawParserFrame::AddChild);
    Connect(ID_BUTTON_COPYALL,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&DFRawParserFrame::copyAllTagNames);
    Connect(ID_BUTTON_DELCHILD,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&DFRawParserFrame::DeleteChild);
    Connect(ID_BUTTON_PARSETOXML,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&DFRawParserFrame::ParseFile);
    Connect(ID_BUTTON_PARSETORAW,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&DFRawParserFrame::ParseFileToRaw);
    Connect(idMenuNew,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&DFRawParserFrame::OnNew);
    Connect(idMenuSave,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&DFRawParserFrame::OnSave);
    Connect(idMenuLoad,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&DFRawParserFrame::OnLoad);
    Connect(idMenuQuit,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&DFRawParserFrame::OnQuit);
    Connect(idMenuHelp,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&DFRawParserFrame::DisplayHelp);
    Connect(idMenuAbout,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&DFRawParserFrame::OnAbout);
    //*)
}

DFRawParserFrame::~DFRawParserFrame()
{
    //(*Destroy(DFRawParserFrame)
    //*)
}

void DFRawParserFrame::OnQuit(wxCommandEvent& event)
{
    Close();
}

void DFRawParserFrame::OnAbout(wxCommandEvent& event)
{
    wxString version = wxString::Format(wxT("%f"), _VERSION);
    wxString msg = _T("DF Raw Parser version ") + version + _T("\n\n") + wxbuildinfo(long_f);
    wxMessageBox(msg, _("Welcome to DF Raw Parser"));
}

void DFRawParserFrame::OnNew(wxCommandEvent& event)
{
    tag_list.clear(); //Clear the vector
    wxString blank = _T("");  //Create a blank string TODO:  DOES THIS REALLY CLEAR THE BOX?!?
    ListBox_Tags->Set(0, &blank);
    ListBox_Arguments->Set(0, &blank);
    ListBox_Children->Set(0, &blank);
}

void DFRawParserFrame::OnSave(wxCommandEvent& event)
{
    if( FileDialog_SaveTagList->ShowModal()==wxID_OK )  //Display the save-file window.
    {
        wxString wxFilename = FileDialog_SaveTagList->GetDirectory()+_("\\")+FileDialog_SaveTagList->GetFilename();  //Get the filename to save as
        string filename( wxFilename.ToAscii() );  //Convert the name to a "string"

        ofstream file(filename.c_str(), ofstream::binary|ofstream::out|ofstream::trunc);  //Open the file for output

        float version_number = _VERSION;  //Get the version number
        file.write(reinterpret_cast<char*>( &version_number ), sizeof(float));  //Write the program version number to the file.

        int tag_count = tag_list.size();  //Get the number of tags to save
        file.write(reinterpret_cast<char*>( &tag_count ), sizeof(int));  //Write the number of tags to the file

        for(int i=0; i<tag_count; i++)  //Loop through the tags
        {
            tag_list.at(i).save(&file);  //Save the tag

            Gauge_Parse->SetRange( tag_count );  //Update the loading bar
            Gauge_Parse->SetValue( i );
            wxPaintEvent();
        }

        file.close();  //Close the file

        Gauge_Parse->SetValue( 0 );  //Reset the loading bar.
    }
}

void DFRawParserFrame::OnLoad(wxCommandEvent& event)
{
    if( FileDialog_OpenTagList->ShowModal()==wxID_OK )  //Open the loading dialog.  If they don't close/cancel the dialog...
    {
        tag_list.clear(); //Clear the vector
        wxString blank = _T("");  //Make a blank string
        ListBox_Tags->Set(0, &blank);  //TODO:  DOES THIS ACTUALLY CLEAR IT?!?
        ListBox_Arguments->Set(0, &blank);
        ListBox_Children->Set(0, &blank);

        wxString wxFilename = FileDialog_OpenTagList->GetDirectory()+_("\\")+FileDialog_OpenTagList->GetFilename();  //Get the file name that they want to load
        string filename( wxFilename.ToAscii() );  //Convert it to a "string"

        ifstream file( filename.c_str() );  //Open the file for input

        float version_number;  //A float to hold the version number
        file.read(reinterpret_cast<char*>( &version_number ), sizeof(float));  //Read the program version number from the file.

        int tag_count;  //An integer to read the total number of tags into.
        file.read(reinterpret_cast<char*>( &tag_count ), sizeof(int));  //Read the number of tags from the file

        for(int i=0; i<tag_count; i++)  //Repeat for the number of tags...
        {
            c_tag newtag;  //Create a blank tag
            newtag.load(&file);  //Load the tag from the file
            tag_list.push_back(newtag);  //Add it to the list

            Gauge_Parse->SetRange( tag_count );  //Update the loading bar
            Gauge_Parse->SetValue( i );
            wxPaintEvent();
        }

        file.close();  //Close the file

        for(unsigned int i=0; i<tag_list.size(); i++)  //Loop through the tags
        {
            wxString newitem(tag_list.at(i).get_raw_name().c_str(), wxConvUTF8);  //Get the name of the tag as a wxString
            ListBox_Tags->Append(newitem);  //Add the string to the listbox
        }

        Gauge_Parse->SetValue( 0 );  //Reset the loading bar.
    }
}



void DFRawParserFrame::AddTag(wxCommandEvent& event)
{
    string str_name( TextCtrl_Tag->GetValue().ToAscii() );  //Get the name in the text-box
    ListBox_Tags->Append( TextCtrl_Tag->GetValue() );  //Add it to the tag-list box
    c_tag newtag;  //Make a new tag
    newtag.set_raw_name( str_name );  //Set the raw name
    newtag.set_xml_name( str_name );  //Set the xml name
    tag_list.push_back(newtag);  //Add the tag to the tag_list vector
}

void DFRawParserFrame::RenameTag(wxCommandEvent& event)
{
    wxString selected = ListBox_Tags->GetStringSelection();  //Get the raw name of the selected tag as a wxString
    int SelectID = ListBox_Tags->GetSelection();  //Get the ID number of the selected tag
    wxString xmlName( tag_list.at(SelectID).get_xml_name().c_str(), wxConvUTF8 );  //Get the xml name of the selected tag as a wxString

    DoubleTextInputDialog* RenameWindow = new DoubleTextInputDialog(0);  //Create a double-text-input dialog to get the new name
    RenameWindow->StaticText1->SetLabel( _("RAW name") );  //Set the labels
    RenameWindow->StaticText2->SetLabel( _("XML name") );
    RenameWindow->TextCtrl1->SetValue( selected );  //Set the text-box contents to the current name.
    RenameWindow->TextCtrl2->SetValue( xmlName );  //Set the text-box contents to the current name.
    RenameWindow->ShowModal();  //Show the dialog as a modal

    ListBox_Tags->SetString( SelectID, RenameWindow->TextCtrl1->GetValue() );  //Set the name of the tag in the list-box to the new name

    string str_name( RenameWindow->TextCtrl1->GetValue().ToAscii() );  //Get a std::string version of the raw name
    string str_xml_name( RenameWindow->TextCtrl2->GetValue().ToAscii() );  //Get a std::string version of the xml name
    tag_list.at(SelectID).set_raw_name(str_name);  //Assign it to the tag in the vector
    tag_list.at(SelectID).set_xml_name(str_xml_name);  //Assign it to the tag in the vector

    RenameWindow->Destroy();  //Destroy the window, so the program can close properly.
}

void DFRawParserFrame::SelectTag(wxCommandEvent& event)
{
    //Clear the argument and chilren boxes
    wxString blank = _T("");
    ListBox_Arguments->Set(0, &blank);
    ListBox_Children->Set(0, &blank);

    int SelectedID = ListBox_Tags->GetSelection();  //Get the ID number of the selected tag

    if( SelectedID != wxNOT_FOUND )  //If a tag is selected (in case they click inside the box, but not on a tag name)
    {
        for(int i=0; i<tag_list.at(SelectedID).get_attribute_count(); i++)  //Loop through the tag's attributes/arguments
        {
            //Add it to the argument box
            wxString attrName( tag_list.at(SelectedID).get_attribute(i).c_str(), wxConvUTF8 );
            ListBox_Arguments->Append( attrName );
        }

        for(int i=0; i<tag_list.at(SelectedID).get_child_count(); i++)  //Loop through the tag's children
        {
            //Add each to the children box
            wxString childName( tag_list.at(SelectedID).get_child(i).c_str(), wxConvUTF8 );
            ListBox_Children->Append( childName );
        }
    }
}

void DFRawParserFrame::AddArgument(wxCommandEvent& event)
{
    int SelectedID = ListBox_Tags->GetSelection();  //Get the selected tag ID
    if(SelectedID!=-1)  //If no tag is selected, SelectedID will have been set to -1
    {
        ListBox_Arguments->Append( TextCtrl_Argument->GetValue() );  //Add the text in the New Argument box as a new argument in the list-box

        string arg_name( TextCtrl_Argument->GetValue().ToAscii() );  //Get a STL string version of the new argument's name
        tag_list.at(SelectedID).add_attribute( arg_name );  //Add the argument to the tag object
    }
}

void DFRawParserFrame::AddChild(wxCommandEvent& event)
{
    int SelectedID = ListBox_Tags->GetSelection();  //Get the selected tag ID
    if(SelectedID!=-1)  //If no tag is selected, SelectedID will have been set to -1
    {
        ListBox_Children->Append( TextCtrl_Child->GetValue() );  //Add the text in the New Child box as a new child in the list-box

        string child_name( TextCtrl_Child->GetValue().ToAscii() );  //Get a STL string version of the new child's name
        tag_list.at(SelectedID).add_child( child_name );  //Add the child to the tag object
    }
}

void DFRawParserFrame::RenameArgument(wxCommandEvent& event)
{
    wxString selected = ListBox_Arguments->GetStringSelection();  //Get the name of the selected argument as a wxString
    int SelectID = ListBox_Arguments->GetSelection();  //Get the ID number of the selected argument
    int SelectTag = ListBox_Tags->GetSelection();  //Get the ID number of the selected tag

    TextInputDialog* RenameWindow = new TextInputDialog(0);  //Create a text-input dialog to get the new name
    RenameWindow->TextCtrl->SetValue( selected );  //Set the text-box contents to the current name.
    RenameWindow->ShowModal();  //Show the dialog as a modal

    ListBox_Arguments->SetString( SelectID, RenameWindow->TextCtrl->GetValue() );  //Set the name of the argument in the list-box to the new name

    string str_name( RenameWindow->TextCtrl->GetValue().ToAscii() );  //Get a std::string version of the name
    tag_list.at(SelectTag).set_attribute_name(SelectID, str_name);  //Assign it to the attribute of the tag in the vector

    RenameWindow->Destroy();  //Destroy the window, so the program can close properly.
}

void DFRawParserFrame::RenaneChild(wxCommandEvent& event)
{
    wxString selected = ListBox_Children->GetStringSelection();  //Get the name of the selected child as a wxString
    int SelectID = ListBox_Children->GetSelection();  //Get the ID number of the selected child
    int SelectTag = ListBox_Tags->GetSelection();  //Get the ID number of the selected tag

    TextInputDialog* RenameWindow = new TextInputDialog(0);  //Create a text-input dialog to get the new name
    RenameWindow->TextCtrl->SetValue( selected );  //Set the text-box contents to the current name.
    RenameWindow->ShowModal();  //Show the dialog as a modal

    ListBox_Children->SetString( SelectID, RenameWindow->TextCtrl->GetValue() );  //Set the name of the child in the list-box to the new name

    string str_name( RenameWindow->TextCtrl->GetValue().ToAscii() );  //Get a std::string version of the name
    tag_list.at(SelectTag).set_child_name(SelectID, str_name);  //Assign it to the child of the tag in the vector

    RenameWindow->Destroy();  //Destroy the window, so the program can close properly.
}

void DFRawParserFrame::ParseFile(wxCommandEvent& event)
{
    //Display the file modal, and if the user clicks OK...
    if( FileDialog_Parse->ShowModal()==wxID_OK )
    {
        //Get the chosen directory/filename
        wxString wxFilename = FileDialog_Parse->GetDirectory()+_("\\")+FileDialog_Parse->GetFilename();
        string filename( wxFilename.ToAscii() );

        string file_contents;  //Create a string to hold the entire contents of the file.
        string line;  //Create a string to read the individual lines into
        ifstream file( filename.c_str() );  //Open the file

        if( file.is_open() )  //If the file was opened properly.
        {
            while( !file.eof() )  //Until we reach the end of the file...
            {
                getline(file, line);  //Read a line into "line"
                file_contents+=line;  //Add the line to file_contents
            }
            file.close();  //Close the file

            vector<string> raw_tags;  //Create a vector to read the tags into

            //Loop through the search results...
            sregex_token_iterator cur( file_contents.begin(), file_contents.end(), Reg_FindTags );  //An iterator for using regex_search on file_contents string
            sregex_token_iterator end;  //The ending iterator

            for( ; cur!=end; cur++)  //Loop through the tags using the iterator
            {
                string newrawtag = cur->str();  //Get the current tag as a string
                newrawtag = newrawtag.substr(1, newrawtag.length()-2);  //Remove the square-brackets
                raw_tags.push_back(newrawtag);  //Add the tag to the vector
            }

            ofstream xml_file( string(stripExtension(filename) + ".xml").c_str() );  //Create a file for output
            vector<c_tag> open_tags;  //A vector to keep track of all the open tags.

            //Loop through the raw tags
            for(unsigned int i=0; i<raw_tags.size(); i++)
            {
                bool found_match = false;  //Set to true when a tag is matched

                vector<string> tag_data;  //A vector to hold the parts of the tag
                tokenize(raw_tags.at(i), tag_data, ":");  //Split the tag into the vector at the colons (:)

                //Loop through the tags
                for(unsigned int j=0; j<tag_list.size(); j++)
                {
                    if( toLower(tag_list.at(j).get_raw_name()) == toLower(tag_data.at(0)) )  //If the name matches, not case-sensitive
                    {
                        //Get the XML name of the tag
                        string XMLName = tag_list.at(j).get_xml_name();
                        if( CheckBox_XMLNames->IsChecked() )  //If the "Auto-lowercase" checkbox is checked...
                        {
                            XMLName = toLower(XMLName);  //Make the string version of the name all lowercase.
                        }

                        if( !open_tags.empty() )
                        {
                            //Loop backwards through the open tags if there are any
                            for(int k=open_tags.size()-1; k>=0; k--)
                            {
                                bool found_match = false;
                                //Loop through possible child tags
                                for(int child=0; child<open_tags.at(k).get_child_count(); child++)
                                {
                                    //If it matches
                                    if( toLower(open_tags.at(k).get_child(child))==toLower(tag_list.at(j).get_raw_name()) )
                                    {
                                        found_match = true;
                                        break;
                                    }
                                    else
                                    {
                                        continue;
                                    }
                                }
                                //If this tag cannot be a child of the open tag
                                if( found_match == false )
                                {
                                    //Copy the name to a string...
                                    string tagname = open_tags.at(k).get_xml_name();
                                    if( CheckBox_XMLNames->IsChecked() ) {tagname = toLower(tagname);}  //If the to-lowercase box is checked, make it lowercase
                                    //Remove the tag from the open list
                                    open_tags.erase( open_tags.begin()+k );
                                    //Close the tag
                                    xml_file << getIndent(open_tags) << "</" << tagname << ">" << endl;
                                }
                                else
                                {
                                    //break out of the loop
                                    break;
                                }
                            }
                        }

                        //If current tag has no child tags
                        if( tag_list.at(j).get_child_count()==0 )
                        {
                            //If the current tag has no arguments
                            if( tag_data.size()==1 )
                            {
                                //Add indentation and the single tag (<name />)
                                xml_file << getIndent(open_tags) << "<" << XMLName << " />" << endl;
                            }
                            //If the current tag has only one argument
                            if( tag_data.size()==2 )
                            {
                                //Add the open tag (<name>)
                                xml_file << getIndent(open_tags) << "<" << XMLName << ">";
                                //Add the contents of the single argument
                                xml_file << tag_data.at(1);
                                //Add the closing tag (<name>)
                                xml_file << "</" << XMLName << ">" << endl;
                            }
                            //If the current tag has multiple arguments
                            if( tag_data.size()>2 )
                            {
                                //Add the opening tag (<name>)
                                xml_file << getIndent(open_tags) << "<" << XMLName << ">" << endl;
                                //Loop through the arguments
                                for(int k=1; k<int(tag_data.size()); k++)
                                {
                                    //Add the opening tag for the argument
                                    xml_file << getIndent(open_tags) << "\t<" << tag_list.at(j).get_attribute(k-1) << ">";
                                    //Add the value for the argument
                                    xml_file << tag_data.at(k);
                                    //Add the closing tag for the argument
                                    xml_file << "</" << tag_list.at(j).get_attribute(k-1) << ">" << endl;
                                }
                                //Add the closing tag
                                xml_file << getIndent(open_tags) << "</" << XMLName << ">" << endl;
                            }
                        }
                        else  //Else (if the tag has children)
                        {
                            //Add opening tag (<name>)
                            xml_file << getIndent(open_tags) << "<" << XMLName << ">" << endl;
                            //Loop through the arguments
                            for(int k=1; k<int(tag_data.size()); k++)
                            {
                                //Add the opening tag for the argument
                                xml_file << getIndent(open_tags) << "\t<" << tag_list.at(j).get_attribute(k-1) << ">";
                                //Add the value for the argument
                                xml_file << tag_data.at(k);
                                //Add the closing tag for the argument
                                xml_file << "</" << tag_list.at(j).get_attribute(k-1) << ">" << endl;
                            }
                            //Add the tag to the open list
                            open_tags.push_back( tag_list.at(j) );
                        }

                        found_match = true;  //We've found a match for this tag
                        break;  //Break out of the loop, we don't want to add it twice
                    }
                }

                if(found_match == false)  //If we didn't find a match
                {
                    error_report( "Tag not matched: "+tag_data.at(0) );  //Output to the error log.
                }

                //Update the progress bar
                Gauge_Parse->SetRange( raw_tags.size() );
                Gauge_Parse->SetValue( i );
                wxPaintEvent();
            }

            //If there are any open tags
            if( !open_tags.empty() )
            {
                //Loop backwards through the open tags
                for(int k=open_tags.size()-1; k>=0; k--)
                {
                    //Copy the name to a string...
                    string tagname = open_tags.at(k).get_xml_name();
                    if( CheckBox_XMLNames->IsChecked() ) {tagname = toLower(tagname);}  //If the to-lowercase box is checked, make it lowercase
                    //Remove the tag from the open list
                    open_tags.erase( open_tags.begin()+k );
                    //Close the tag
                    xml_file << getIndent(open_tags) << "</" << tagname << ">" << endl;
                }
            }

            Gauge_Parse->SetValue( 0 );  //Reset the loading bar
            file.close();  //Close the file
        }
        else  // !file.is_open()
        {
            wxString msg = _T("ERROR: COULD NOT OPEN FILE: ")+wxFilename;  //Create an error message
            wxMessageBox(msg, _("Error"));  //Open a dialog to display it.
        }
    }
}

void DFRawParserFrame::DeleteTag(wxCommandEvent& event)
{
    int SelectedID = ListBox_Tags->GetSelection();  //Get the ID number of the selected tag

    //If there is a tag selected
    if( SelectedID != wxNOT_FOUND )
    {
        //Remove from list-box
        ListBox_Tags->Delete(SelectedID);
        //Remove from vector
        tag_list.erase( tag_list.begin()+SelectedID );

        //Clear the argument and chilren boxes
        wxString blank = _T("");
        ListBox_Arguments->Set(0, &blank);
        ListBox_Children->Set(0, &blank);
    }
}

void DFRawParserFrame::DeleteArgument(wxCommandEvent& event)
{
    int SelectedTag = ListBox_Tags->GetSelection();  //Get the ID number of the selected tag
    int SelectedArg = ListBox_Arguments->GetSelection();  //Get the ID number of the selected argument

    //If there is a tag selected
    if( SelectedTag!=wxNOT_FOUND and SelectedArg!=wxNOT_FOUND)
    {
        //Remove it from the list-box
        ListBox_Arguments->Delete(SelectedArg);
        //Remove it from the vector
        tag_list.at(SelectedTag).del_attribute(SelectedArg);
    }
}

void DFRawParserFrame::DeleteChild(wxCommandEvent& event)
{
    int SelectedTag = ListBox_Tags->GetSelection();  //Get the ID number of the selected tag
    int SelectedChild = ListBox_Children->GetSelection();  //Get the ID number of the selected child

    //If there is a tag selected
    if( SelectedTag!=wxNOT_FOUND and SelectedChild!=wxNOT_FOUND)
    {
        //Remove it from the list-box
        ListBox_Children->Delete(SelectedChild);
        //Remove it from the vector
        tag_list.at(SelectedTag).del_child(SelectedChild);
    }
}

void DFRawParserFrame::DisplayHelp(wxCommandEvent& event)
{
    string path = getPath();  //Get's the path of the progam
    wxString wxPath(path.c_str(), wxConvUTF8);  //Turn it into a wxPath
    wxLaunchDefaultBrowser(wxPath+_("help.html"));  //Try to open a file called "help.html" inside the same path as this path.
}

void DFRawParserFrame::copyAllTagNames(wxCommandEvent& event)
{
    int SelectedID = ListBox_Tags->GetSelection();  //Get the ID number of the selected tag

    //If there is a tag selected
    if( SelectedID != wxNOT_FOUND )
    {
        tag_list.at(SelectedID).del_all_children();  //Delete all the children of the selected tag from the tag_list vector
        ListBox_Children->Clear();  //Clear the list-box
        for(unsigned int i=0; i<tag_list.size(); i++)  //Loop through each tag in the tag_list vector
        {
            string name = tag_list.at(i).get_raw_name();  //Get the raw name of the tag
            wxString wxName(name.c_str(), wxConvUTF8);  //Convert the string to wxString
            ListBox_Children->Append( wxName );  //Add the copy of the tag as a child to the selected tag
            tag_list.at(SelectedID).add_child( name );  //Add the child to the tag object
        }
    }
}

void DFRawParserFrame::ParseFileToRaw(wxCommandEvent& event)
{
    //Display the file modal, and if the user clicks OK...
    if( FileDialog_ParseToRaw->ShowModal()==wxID_OK )
    {
        //Get the chosen directory/filename
        wxString wxFilename = FileDialog_ParseToRaw->GetDirectory()+_("\\")+FileDialog_ParseToRaw->GetFilename();
        string filename( wxFilename.ToAscii() );  //Convert it to "string" format

        //Load the input file
        XMLNode xMainNode=XMLNode::openFileHelper(filename.c_str(), "Object");
        //Open the output file
        ofstream outputFile(string(stripExtension(filename) + ".txt").c_str());

        //Get weather output tags should be uppercase...
        bool uppercase = CheckBox_RAWNames->IsChecked();

        //Start output
        outputNode(outputFile, tag_list, xMainNode, 0, uppercase);
    }
}
